import SockJS from 'sockjs-client';
import {
	CompatClient,
	Frame,
	Message,
	Stomp,
	StompHeaders,
	StompSubscription,
} from '@stomp/stompjs';

export interface StompConnectInfo {
	frame: Frame;
	client: StompClient;
}

export interface StompSubscriptionInfo {
	message: Message;
	subscription: StompSubscription;
}

export class StompClient {
	readonly origin: CompatClient;

	constructor(brokerURL: string) {
		if (brokerURL.indexOf('ws') === 0) {
			this.origin = Stomp.client(brokerURL);
		} else {
			this.origin = Stomp.over(new SockJS(brokerURL));
		}
		// eslint-disable-next-line
		this.origin.debug = () => {};
	}

	connect = (headers?: StompHeaders): Promise<StompConnectInfo> => {
		return new Promise<StompConnectInfo>((resolve, reject) => {
			this.origin.connect(
				headers,
				(frame: Frame) => {
					resolve({
						frame,
						client: this,
					});
				},
				(error: Error) => {
					reject(error);
				}
			);
		});
	};

	disconnect = (headers?: StompHeaders): Promise<StompConnectInfo> => {
		return new Promise<StompConnectInfo>(resolve => {
			this.origin.disconnect((frame: Frame) => {
				resolve({
					frame,
					client: this,
				});
			}, headers);
		});
	};

	subscribe = (
		destination: string,
		callback: (info: StompSubscriptionInfo) => void,
		headers?: StompHeaders
	): void => {
		const subscription = this.origin.subscribe(
			destination,
			message => {
				callback({
					message,
					subscription,
				});
			},
			headers
		);
	};

	send = <T>(destination: string, data: T, headers?: StompHeaders): void => {
		this.origin.send(destination, headers, JSON.stringify(data));
	};
}
